const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const sqlite3 = require('sqlite3').verbose();
const cors = require('cors');
const path = require('path');

const app = express();
const server = http.createServer(app);
// WebSocket服务器设置
const wss = new WebSocket.Server({ server });

app.use(cors());
app.use(express.json());

// 初始化SQLite数据库
const db = new sqlite3.Database('chat.db');

// 创建用户表
db.run(`
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT UNIQUE NOT NULL,
    online BOOLEAN DEFAULT FALSE,
    last_seen DATETIME DEFAULT CURRENT_TIMESTAMP
  )
`);

// 创建消息表
db.run(`
  CREATE TABLE IF NOT EXISTS messages (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    sender_id INTEGER NOT NULL,
    receiver_id INTEGER NOT NULL,
    content TEXT NOT NULL,
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (sender_id) REFERENCES users (id),
    FOREIGN KEY (receiver_id) REFERENCES users (id)
  )
`);

// 存储在线用户和他们的WebSocket连接
const onlineUsers = new Map(); // username -> WebSocket
const userSockets = new Map(); // WebSocket -> username

// WebSocket连接处理
// WebSocket连接事件处理：当有新的客户端连接时触发
wss.on('connection', (ws) => {
  console.log('新的WebSocket连接');

  // 处理客户端发送的消息
  ws.on('message', (data) => {
    try {
      const message = JSON.parse(data);
      handleMessage(ws, message);
    } catch (error) {
      console.error('消息解析错误:', error);
      ws.send(JSON.stringify({ type: 'error', content: '无效的消息格式' }));
    }
  });

  // 处理客户端断开连接
  ws.on('close', () => {
    const username = userSockets.get(ws);
    if (username) {
      onlineUsers.delete(username);
      userSockets.delete(ws);
      
      // 更新用户在线状态
      db.run('UPDATE users SET online = FALSE, last_seen = CURRENT_TIMESTAMP WHERE username = ?', [username], (err) => {
        if (err) {
          console.error('更新用户状态错误:', err);
        }
      });
      
      // 广播更新后的用户列表
      broadcastUserList();
      console.log(`用户 ${username} 断开连接`);
    }
  });

  // 处理WebSocket错误
  ws.on('error', (error) => {
    console.error('WebSocket错误:', error);
  });
});

/**
 * 处理WebSocket消息的主函数
 * @param {WebSocket} ws - WebSocket连接对象
 * @param {Object} message - 解析后的消息对象
 * @param {string} message.type - 消息类型（login/message/get_history）
 */
function handleMessage(ws, message) {
  switch (message.type) {
    case 'login':
      handleLogin(ws, message);
      break;
    case 'message':
      handleSendMessage(ws, message);
      break;
    case 'get_history':
      handleGetHistory(ws, message);
      break;
    default:
      ws.send(JSON.stringify({ type: 'error', content: '未知的消息类型' }));
  }
}

/**
 * 处理用户登录请求
 * @param {WebSocket} ws - WebSocket连接对象
 * @param {Object} message - 登录消息
 * @param {string} message.username - 用户名
 */
function handleLogin(ws, message) {
  const { username } = message;
  
  if (!username) {
    ws.send(JSON.stringify({ type: 'error', content: '用户名不能为空' }));
    return;
  }

  // 插入或更新用户
  db.run('INSERT OR IGNORE INTO users (username) VALUES (?)', [username], function(err) {
    if (err) {
      console.error('插入用户错误:', err);
      ws.send(JSON.stringify({ type: 'error', content: '登录失败' }));
      return;
    }
    
    db.run('UPDATE users SET online = TRUE, last_seen = CURRENT_TIMESTAMP WHERE username = ?', [username], (err) => {
      if (err) {
        console.error('更新用户状态错误:', err);
        ws.send(JSON.stringify({ type: 'error', content: '登录失败' }));
        return;
      }

      // 存储用户连接
      onlineUsers.set(username, ws);
      userSockets.set(ws, username);

      // 发送登录成功消息
      ws.send(JSON.stringify({ type: 'login_success', username }));
      
      // 广播更新后的用户列表
      broadcastUserList();
      
      console.log(`用户 ${username} 登录成功`);
    });
  });
}

/**
 * 处理发送消息请求
 * @param {WebSocket} ws - WebSocket连接对象
 * @param {Object} message - 消息对象
 * @param {string} message.to - 接收者用户名
 * @param {string} message.content - 消息内容
 */
function handleSendMessage(ws, message) {
  const { to, content } = message;
  const from = userSockets.get(ws);
  
  if (!from) {
    ws.send(JSON.stringify({ type: 'error', content: '请先登录' }));
    return;
  }

  if (!to || !content) {
    ws.send(JSON.stringify({ type: 'error', content: '接收者或消息内容不能为空' }));
    return;
  }

  // 获取用户ID
  db.get('SELECT id FROM users WHERE username = ?', [from], (err, fromUser) => {
    if (err || !fromUser) {
      ws.send(JSON.stringify({ type: 'error', content: '发送者不存在' }));
      return;
    }

    db.get('SELECT id FROM users WHERE username = ?', [to], (err, toUser) => {
      if (err || !toUser) {
        ws.send(JSON.stringify({ type: 'error', content: '接收者不存在' }));
        return;
      }

      // 插入消息到数据库
      db.run('INSERT INTO messages (sender_id, receiver_id, content) VALUES (?, ?, ?)', 
        [fromUser.id, toUser.id, content], 
        function(err) {
          if (err) {
            console.error('插入消息错误:', err);
            ws.send(JSON.stringify({ type: 'error', content: '发送消息失败' }));
            return;
          }
          
          const timestamp = new Date().toISOString();
          
          // 构建消息对象
          const messageObj = {
            type: 'message',
            from: from,
            to: to,
            content: content,
            timestamp: timestamp,
            id: this.lastID
          };

          // 发送给发送者（确认）
          ws.send(JSON.stringify(messageObj));
          
          // 发送给接收者（如果在线）
          const toSocket = onlineUsers.get(to);
          if (toSocket) {
            toSocket.send(JSON.stringify(messageObj));
          }
        }
      );
    });
  });
}

/**
 * 处理获取历史消息请求
 * @param {WebSocket} ws - WebSocket连接对象
 * @param {Object} message - 请求对象
 * @param {string} message.withUser - 目标用户名
 */
function handleGetHistory(ws, message) {
  const { withUser } = message;
  const currentUser = userSockets.get(ws);
  
  if (!currentUser) {
    ws.send(JSON.stringify({ type: 'error', content: '请先登录' }));
    return;
  }

  // 获取用户ID
  db.get('SELECT id FROM users WHERE username = ?', [currentUser], (err, currentUserObj) => {
    if (err || !currentUserObj) {
      ws.send(JSON.stringify({ type: 'error', content: '当前用户不存在' }));
      return;
    }

    db.get('SELECT id FROM users WHERE username = ?', [withUser], (err, withUserObj) => {
      if (err || !withUserObj) {
        ws.send(JSON.stringify({ type: 'error', content: '对方用户不存在' }));
        return;
      }

      // 查询历史消息
      db.all(`
        SELECT m.*, u1.username as sender_name, u2.username as receiver_name
        FROM messages m
        JOIN users u1 ON m.sender_id = u1.id
        JOIN users u2 ON m.receiver_id = u2.id
        WHERE (m.sender_id = ? AND m.receiver_id = ?) OR (m.sender_id = ? AND m.receiver_id = ?)
        ORDER BY m.timestamp ASC
      `, [currentUserObj.id, withUserObj.id, withUserObj.id, currentUserObj.id], (err, history) => {
        if (err) {
          console.error('查询历史消息错误:', err);
          ws.send(JSON.stringify({ type: 'error', content: '获取历史消息失败' }));
          return;
        }
        
        // 格式化历史消息
        const formattedHistory = history.map(msg => ({
          id: msg.id,
          type: 'message',
          from: msg.sender_name,
          to: msg.receiver_name,
          content: msg.content,
          timestamp: msg.timestamp
        }));
        
        ws.send(JSON.stringify({ type: 'history', messages: formattedHistory }));
      });
    });
  });
}

/**
 * 广播在线用户列表给所有连接的用户
 * 从数据库获取在线用户并发送给每个客户端
 */
function broadcastUserList() {
  db.all('SELECT username FROM users WHERE online = TRUE', (err, rows) => {
    if (err) {
      console.error('获取在线用户列表错误:', err);
      return;
    }
    
    const onlineUsersList = rows.map(row => row.username);
    const userListMessage = JSON.stringify({
      type: 'user_list',
      users: onlineUsersList
    });
    
    // 广播给所有在线用户
    onlineUsers.forEach((socket, username) => {
      socket.send(userListMessage);
    });
  });
}

// 启动服务器
const PORT = process.env.PORT || 3001;
server.listen(PORT, () => {
  console.log(`服务器运行在端口 ${PORT}`);
});